from odoo import fields, api, models, _
from odoo.exceptions import ValidationError


class SaleOrder(models.Model):
    _inherit = 'sale.order'

    s_show_state = fields.Selection([
        ('draft', 'Confirming'),
        ('active', 'Active'),
        ('closed', 'Completed'),
        ('cancelled', 'Cancelled'),
        ('hold', 'Hold On')
    ], tracking=True, store=True, string='MO States', default='active', compute='_compute_s_show_state')
    # 禁止出货
    s_disable_delivery = fields.Boolean(string='禁止出货', tracking=True)

    origin_planned_receiving_date = fields.Datetime(string='Origin Factory DD',
                                                    help="This is the original planned receiving date.")
    sb_plan_change_apply_count = fields.Integer(
        string="Order Plan Change Apply count",
        compute="_compute_sb_plan_change_apply_count",
    )
    sb_plan_change_apply_ids = fields.One2many('sb.plan.change.apply', 'sale_order_id',
                                               string='Order Plan Change Apply')

    def _compute_sb_plan_change_apply_count(self):
        for record in self:
            record.sb_plan_change_apply_count = len(record.sb_plan_change_apply_ids)

    @api.depends('status', 'state', 'order_line.s_mrp_production_ids.state')
    def _compute_s_show_state(self):
        """
        計算銷售訂單嘅可見狀態（show state）。
        主要係根據訂單嘅主狀態，同埋相關製造訂單(mrp)嘅狀態嚟決定。
        """
        for rec in self:
            if rec.status == 'hold' and (
                    not rec.mrp_production_ids or all(mrp.s_order_suspension for mrp in rec.mrp_production_ids)):
                rec.s_show_state = 'hold'
            elif rec.status == 'cancelled' and (
                    not rec.mrp_production_ids or all(mrp.state == 'cancel' for mrp in rec.mrp_production_ids)):
                rec.s_show_state = 'cancelled'
            elif rec.status == 'closed' or rec.status == 'completed':
                rec.s_show_state = 'closed'
            elif rec.state == 'draft' and rec.sb_workflow_state in ['approval', 'fail_to_approve']:
                rec.s_show_state = 'draft'
            else:
                rec.s_show_state = 'active'

    def version_action_confirm(self):
        """ Confirm the given quotation(s) and set their confirmation date.
        If the corresponding setting is enabled, also locks the Sale Order.
        :return: True
        :rtype: bool
        :raise: UserError if trying to confirm cancelled SO's
        """

        self.order_line._validate_analytic_distribution()

        for order in self:
            order.validate_taxes_on_sales_order()
            if order.partner_id in order.message_partner_ids:
                continue
            order.message_subscribe([order.partner_id.id])

        self.write(self._prepare_confirmation_values())

        # Context key 'default_name' is sometimes propagated up to here.
        # We don't need it and it creates issues in the creation of linked records.
        context = self._context.copy()
        context.pop('default_name', None)

        self.with_context(context)._action_confirm()

        self.filtered(lambda so: so._should_be_locked()).action_lock()

        if self.env.context.get('send_email'):
            self._send_order_confirmation_mail()

        return True

    def create_shipping_instructions(self):
        records = self.env['sale.order'].browse(
            self._context.get('active_ids', []))
        for rec in records:
            # 锁MO
            if rec.s_disable_delivery:
                # 当前订单已经锁定，不允许出货
                raise ValidationError(
                    _('The current order has been locked and cannot be shipped 【{}】'.format(rec.name)))
            # 锁厂编
            if rec.product_id.s_disable_delivery:
                raise ValidationError(_('Product Code:【{}】,  Shipping has been prohibited'.format(rec.product_id.name)))
        return super(SaleOrder, self).create_shipping_instructions()

    def action_view_plan_change_apply(self):
        self.ensure_one()
        action = self.sudo().env.ref('sb_order_changes.sb_plan_change_apply_act_window').read()[0]
        action['domain'] = [('sale_order_id', '=', self.id)]
        return action


class SaleOrderLine(models.Model):
    _inherit = 'sale.order.line'

    @api.depends('product_id', 'product_uom', 'product_uom_qty')
    def _compute_price_unit(self):
        if self._context.get('ecr_apply', False):
            return
        for line in self:
            # check if there is already invoiced amount. if so, the price shouldn't change as it might have been
            # manually edited
            if line.qty_invoiced > 0 or (line.product_id.expense_policy == 'cost' and line.is_expense):
                continue
            if not line.product_uom or not line.product_id:
                line.price_unit = 0.0
            else:
                line = line.with_company(line.company_id)
                price = line._get_display_price()
                line.price_unit = line.product_id._get_tax_included_unit_price_from_price(
                    price,
                    line.currency_id or line.order_id.currency_id,
                    product_taxes=line.product_id.taxes_id.filtered(
                        lambda tax: tax.company_id == line.env.company
                    ),
                    fiscal_position=line.order_id.fiscal_position_id,
                )

    price_unit = fields.Float(string='Unit Price', digits='Sale Unit Price')
    is_allow_lot = fields.Boolean(string='Cannot be fed', compute='_compute_is_allow_lot')

    @api.depends('write_date')
    def _compute_is_allow_lot(self):
        for rec in self:
            is_allow_lot = False
            if rec.order_id.is_lock:
                is_allow_lot = True
            if rec.order_id.status == 'hold':
                is_allow_lot = True
            if rec.order_id.status == 'closed':
                is_allow_lot = True
            if rec.order_id.status == 'cancelled':
                is_allow_lot = True
            # erp锁单
            if rec.product_template_id.s_disable_down_card:
                is_allow_lot = True
            rec.is_allow_lot = is_allow_lot

    def action_select_sale_to_wizard(self):
        for rec in self:
            if rec.is_allow_lot:
                raise ValidationError('当前订单或物料已锁定不允许下卡')
        return super(SaleOrderLine, self).action_select_sale_to_wizard()
